package com.mapbased.wfw;

import java.io.*;

import org.xml.sax.*;

public class WfwEntityResolver
    implements EntityResolver
{
    public static final String BASE_LOCATION="mapbased-entity-cache";
    public static final EntityResolver INSTANCE=new WfwEntityResolver();
    private WfwEntityResolver()
    {
    }

    /**
     * Allow the application to resolve external entities.
     *
     * @param publicId The public identifier of the external entity being
     *   referenced, or null if none was supplied.
     * @param systemId The system identifier of the external entity being
     *   referenced.
     * @return An InputSource object describing the new input source, or
     *   null to request that the parser open a regular URI connection to
     *   the system identifier.
     * @throws SAXException Any SAX exception, possibly wrapping another
     *   exception.
     * @throws IOException A Java-specific IO exception, possibly the result
     *   of creating a new InputStream or Reader for the InputSource.
     * @todo Implement this org.xml.sax.EntityResolver method
     */
    public InputSource resolveEntity(String publicId,String systemId)
        throws SAXException,IOException
    {
        if(!systemId.startsWith("http"))
        {
            return null;
        }
        java.net.URL u=new java.net.URL(systemId);
        File localfile=new File(BASE_LOCATION,
                                u.getHost() + "/" + u.getPath());

        if(localfile.exists())
        {
            InputSource is= new InputSource(
                new java.io.BufferedInputStream(
                    new java.io.FileInputStream(localfile)));
                        is.setPublicId(publicId);
                        is.setSystemId(systemId);

                    return is;
        }
        else
        {

            return new  InputSource(new java.io.ByteArrayInputStream(
                                    this.download(u,localfile)
                                    ));
        }


    }
    private synchronized byte[] download(java.net.URL u,File localfile)
        throws IOException
    {
        localfile.getParentFile().mkdirs();

        java.io.ByteArrayOutputStream bos=new java.io.ByteArrayOutputStream(
            1024);
        this.readUrl(u,bos);
        byte [] bts=bos.toByteArray();
        OutputStream os=null;
        try
        {
            os=new java.io.BufferedOutputStream
                (new java.io.FileOutputStream(localfile,false));
            os.write(bts);
        }
        finally
        {
            if(os != null)
            {
                os.close();
            }
        }
        return bts;


    }

    private void readUrl(java.net.URL u,java.io.ByteArrayOutputStream bos)
        throws IOException
    {
        java.io.InputStream is=null;
        try
        {
            is=u.openStream();
            int i=is.read();
            while(i >= 0)
            {
                bos.write(i);
                i=is.read();
            }
        }
        finally
        {
            if(is != null)
            {
                is.close();
            }
        }

    }

}
